#include "tcpdatareader.h"

#include <iostream>

TcpDataReader::TcpDataReader(QObject *parent) :
	QObject(parent), bConnected(false), dataMutex(new QMutex(QMutex::Recursive))
{
  connect(&tcpSocket, SIGNAL(connected()), this, SLOT(on_connectedToServer()));
  connect(&tcpSocket, SIGNAL(disconnected()), this, SLOT(on_connectionClosedByServer()));
  connect(&tcpSocket, SIGNAL(readyRead()), this, SLOT(updateData()));

}

void TcpDataReader::on_closeConnection()
{
    tcpSocket.close();
    bConnected = false;

    emit connected(false);
}

void TcpDataReader::on_connectedToServer()
{
    qDebug("connected to server");
    bConnected = true;

    emit connected(true);
}

void TcpDataReader::on_connectionClosedByServer()
{
    on_closeConnection();

    qDebug("disconnected from the server");
    emit connected(false);
}

void TcpDataReader::connectToServer()
{
    tcpSocket.connectToHost(QHostAddress::LocalHost, 33333);

    qDebug("connecting to server...");

    nextBlockSize = 0;
}

void TcpDataReader::disconnectFromServer()
{
    on_closeConnection();
}

void TcpDataReader::updateData()
{
    QDataStream in(&tcpSocket);
    in.setVersion(QDataStream::Qt_4_1);

    forever
    {
	if (nextBlockSize == 0)
	{
	    if (tcpSocket.bytesAvailable() < sizeof(quint16))
		break;
	    in >> nextBlockSize;
	    std::cout << "about to read " << nextBlockSize << " bytes" << std::endl;
	}

	if (nextBlockSize == 0xFFFF)
	{
	    on_closeConnection();
	    qDebug("no more data from server");
	    break;
	}

	if (tcpSocket.bytesAvailable() < nextBlockSize)
	    break;

	QByteArray bytes(nextBlockSize, '\0');

	in.readRawData(bytes.data(), nextBlockSize);
//	std::cout << "enqueuing " << bytes.size() << " bytes (" << nextBlockSize << ")" << std::endl;
	frames.enqueue(bytes);

	nextBlockSize = 0;

	emit newData();
    }
}

int TcpDataReader::getNFrames()
{
    int nFrames;

    dataMutex->lock();
    nFrames = frames.size();
    dataMutex->unlock();

    return nFrames;

}

bool TcpDataReader::isConnected() const
{
    return bConnected;
}

QByteArray TcpDataReader::popData()
{
    QByteArray bytes;

    dataMutex->lock();
    if(getNFrames() > 0)
    {
//	std::cout << frames[0].size() << std::endl;
	bytes = QByteArray(frames.dequeue());
//	std::cout << bytes.size() << std::endl;
    }
    else
    {
	bytes = QByteArray();
    }
    dataMutex->unlock();

    return bytes;
}
